{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c3daeb24",
   "metadata": {
    "id": "c3daeb24"
   },
   "source": [
    "# Youtube Transcript Search QA Bot\n",
    "![picture](https://qph.cf2.quoracdn.net/main-qimg-5a926a036070e4e2ea33283dbe26c17c-pjlq)\n",
    "\n",
    "This Q&A bot will allow you to search through youtube transcripts using natural language! By going through this notebook, we'll introduce how you can use LanceDB to store and manage your data easily.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b29e1754-a01e-41e4-804a-a6f5dac8f033",
   "metadata": {
    "id": "b29e1754-a01e-41e4-804a-a6f5dac8f033"
   },
   "source": [
    "### Install dependencies"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "e7b8f4e8",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "e7b8f4e8",
    "outputId": "f7a6b9fb-5ff2-49f4-facb-91e4a9e02a6b"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[?25l   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/76.5 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m76.5/76.5 kB\u001b[0m \u001b[31m3.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25h\u001b[?25l   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/480.6 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r",
      "\u001b[2K   \u001b[91m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[90m╺\u001b[0m \u001b[32m471.0/480.6 kB\u001b[0m \u001b[31m20.4 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\r",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m480.6/480.6 kB\u001b[0m \u001b[31m11.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m116.3/116.3 kB\u001b[0m \u001b[31m6.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m179.3/179.3 kB\u001b[0m \u001b[31m1.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m134.8/134.8 kB\u001b[0m \u001b[31m645.3 kB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m194.1/194.1 kB\u001b[0m \u001b[31m9.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25h\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\n",
      "gcsfs 2024.10.0 requires fsspec==2024.10.0, but you have fsspec 2024.9.0 which is incompatible.\u001b[0m\u001b[31m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m27.4/27.4 MB\u001b[0m \u001b[31m19.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m30.5/30.5 MB\u001b[0m \u001b[31m19.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25h"
     ]
    }
   ],
   "source": [
    "!pip install --quiet openai==0.28 datasets\n",
    "!pip install --quiet -U lancedb"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3e41240e",
   "metadata": {
    "id": "3e41240e"
   },
   "source": [
    "## Download the data\n",
    "For this application we are going to use the HuggingFace dataset -jamescalam/youtube-transcriptions.\n",
    "\n",
    "For more information, you can find the dataset <a href=\"https://huggingface.co/datasets/jamescalam/youtube-transcriptions\">here</a>.\n",
    "\n",
    "We'll use the training a split with 700 videos and 208619 sentences.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "694ceb6f",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 296,
     "referenced_widgets": [
      "f7e2605aae1444ba93b0e8873e66c710",
      "be09a18ab0854f399168acaa5a57cda3",
      "882971e37b274e559d7a3d9c029065ba",
      "82988999764e460cbd4c435746514dd9",
      "2883749ca2f54072a849147fe4c0f0be",
      "e59d39994d6340108e7ada041796ae09",
      "07c75f956f2a44bbb7a8aef05da9e47d",
      "01b65c3144ca40e8a0fbfbf303f684fb",
      "c1e3f428009f4e0f97ae45b68ec22837",
      "fa387c1277b94305a56deae11e712b7c",
      "11511e19450c420180bc94158d97d152",
      "7f3b8ca64a9f466fb020bcd6e391a018",
      "2b067bf2270743a0a45cbe5dc900689d",
      "2e5b114f6c1b4149955657cb2a34080d",
      "6fcfac6966864e7a83a19da9c5a44fb1",
      "1bb0a206d3c44679856815e8d296b0fb",
      "e7cfe22e147b437089934e66083f95cc",
      "71b1afcdebee4cc88a745b4bb8f9a4c6",
      "3083eb9df7974cbb9d9457e77eaa3c75",
      "d8d40be35f564dd8929b5e83e873b008",
      "08cb29d7036d482bbfa1228e02661a89",
      "1ffc287a0c2c4c2ab770291e236f65fe",
      "d02c50753bea40f4bac1ad3f6e88267e",
      "93927f3782514ced828711ec8767ec67",
      "100c06341fa547a59bd9bfd4a870b7e9",
      "3afe3579230b4727ab5e771ec94ec373",
      "5b2deb0177ab4924ae940801a8acbcf4",
      "8acf44f53b014ef99618b2248e411df0",
      "b9f12ffaf38d46f49c13b53e49aa5596",
      "8b9688a3350f4fb8a2e5b4245db6c83d",
      "ea03fce2dd36456caa2563572dcd3c5c",
      "d037238a27584edbbec16dc61a31e76d",
      "75587a5dc9cd4d8eb29a4bec874ea63d"
     ]
    },
    "id": "694ceb6f",
    "outputId": "7e655c25-7410-4b95-c29e-461d89bc9963"
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.10/dist-packages/huggingface_hub/utils/_auth.py:94: UserWarning: \n",
      "The secret `HF_TOKEN` does not exist in your Colab secrets.\n",
      "To authenticate with the Hugging Face Hub, create a token in your settings tab (https://huggingface.co/settings/tokens), set it as secret in your Google Colab and restart your session.\n",
      "You will be able to reuse this secret in all of your notebooks.\n",
      "Please note that authentication is recommended but still optional to access public models or datasets.\n",
      "  warnings.warn(\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "f7e2605aae1444ba93b0e8873e66c710",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "README.md:   0%|          | 0.00/2.13k [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "7f3b8ca64a9f466fb020bcd6e391a018",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "youtube-transcriptions.jsonl:   0%|          | 0.00/79.8M [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "d02c50753bea40f4bac1ad3f6e88267e",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Generating train split:   0%|          | 0/208619 [00:00<?, ? examples/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "Dataset({\n",
       "    features: ['title', 'published', 'url', 'video_id', 'channel_id', 'id', 'text', 'start', 'end'],\n",
       "    num_rows: 208619\n",
       "})"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from datasets import load_dataset\n",
    "\n",
    "data = load_dataset(\"jamescalam/youtube-transcriptions\", split=\"train\")\n",
    "data"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a0be4da6",
   "metadata": {
    "id": "a0be4da6"
   },
   "source": [
    "### Prepare context\n",
    "Each item in the dataset contains just a short chunk of text. We'll need to merge a bunch of these chunks together on a rolling basis. For this demo, we'll merge 20 rows and step over 4 rows at a time. LanceDB offers chaining support so you can write declarative, readable and parameterized queries. Here we serialize to Pandas as well:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "39bbc15e",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 81
    },
    "id": "39bbc15e",
    "outputId": "882030ff-25c6-40b5-91f1-6e45c291d806"
   },
   "outputs": [
    {
     "data": {
      "application/vnd.google.colaboratory.intrinsic+json": {
       "summary": "{\n  \"name\": \"df\",\n  \"rows\": 52250,\n  \"fields\": [\n    {\n      \"column\": \"title\",\n      \"properties\": {\n        \"dtype\": \"category\",\n        \"num_unique_values\": 699,\n        \"samples\": [\n          \"Defer - Go Lang Practical  Programming Tutorial p.20\",\n          \"Short Term vs Long Term Satisfaction\",\n          \"NNFS Update #2: Content done\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"published\",\n      \"properties\": {\n        \"dtype\": \"category\",\n        \"num_unique_values\": 699,\n        \"samples\": [\n          \"2017-11-11 14:07:07\",\n          \"2017-06-22 09:44:05\",\n          \"2020-09-25 17:49:03\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"url\",\n      \"properties\": {\n        \"dtype\": \"category\",\n        \"num_unique_values\": 699,\n        \"samples\": [\n          \"https://youtu.be/aVDkuViaJfY\",\n          \"https://youtu.be/YaPXHoOo9Pw\",\n          \"https://youtu.be/SN0VwEt2huo\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"video_id\",\n      \"properties\": {\n        \"dtype\": \"category\",\n        \"num_unique_values\": 699,\n        \"samples\": [\n          \"aVDkuViaJfY\",\n          \"YaPXHoOo9Pw\",\n          \"SN0VwEt2huo\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"channel_id\",\n      \"properties\": {\n        \"dtype\": \"category\",\n        \"num_unique_values\": 5,\n        \"samples\": [\n          \"UCr8O8l5cCX85Oem1d18EezQ\",\n          \"UCobqgqE4i5Kf7wrxRxhToQA\",\n          \"UCZHmQk67mSJgfCCTn7xBfew\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"id\",\n      \"properties\": {\n        \"dtype\": \"string\",\n        \"num_unique_values\": 52250,\n        \"samples\": [\n          \"Nz7xzUybpFM-t2614.2\",\n          \"n622girLRNM-t2165.1200000000003\",\n          \"pPBqM4CKjUU-t2520.8799999999997\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"text\",\n      \"properties\": {\n        \"dtype\": \"string\",\n        \"num_unique_values\": 52238,\n        \"samples\": [\n          \"And the level generator would generate this level. And so you're basically your distance metric between environments was a vector of size five, right? This is environment one. And you had environment two, which if it's more, it has higher stumps, right? Then this particular number here maybe would be higher than this number here. So it was kind of limited to taking the Euclidean distance between two environment encodings in order to measure the distance between environments. This is very, very domain-specific. And the authors here argue what we should rather do is have a general environment agnostic distance metric, right? So here is what they propose. They propose the following. Why don't we, if we have a new environment, right? Let's say we have a new environment. We measure all of the agents, the current agents and the ones we've already seen, right? We measure all the agents in our database on this new environment. That's this. And they come up with scores, right? Each of them gets a score. And then we, you know, clip and bound the score. So the max here is 300 and the minimum is 50. But in any case, we then rank them, right? So we evaluate them, and then we rank them from best to worst. And then we normalize, which simply means that the best one gets a score of 0.5 and the worst one gets a score of negative 0.5. And now this vector here, this is now used to compare environments. So if we have another environment, right? Right here, we have E2.\",\n          \"I mean, maybe in the first generations you could help to have a surrogate model that somehow helps you to sort out the things that are really bad. Like this will not grow into anything. So I think you could use it there. Later, I guess you would probably have to run the system when things get more complex. But I think there's also another role for these surrogate models, which is something I always wanted to try to predict. Basically, the learning abilities of these systems. So you have an agent and an environment. So maybe you don't need to simulate the whole lifetime. But you can have some kind of some test that would test how capable is this agent. So having some kind of surrogate that could look at certain parts of the neural network and already predict, will this be a good learner or not? Basically, but yeah. It is in one part, you also, it has very, very, remember, like I got into machine learning and graphical models were the hot thing at that point. It was just before deep learning. And this reminds me all this self-organizing systems with the local communication. They remind me a lot of belief propagation, things like this. Graph neural networks obviously are right now up and coming, let's say. Do you see connections between all of those things or is that just kind of a superficial connection? Yeah, I definitely see there's a big connection to these also these graph neural networks, basically. Like, I mean, they're very close to like a more generalized form, basically, of like a cellular automata where you have different basically neighborhoods. Depending on your topology of the graph. And they also seem to be, I think they're super interesting. Also, actually, how I got into neural networks is the first lecture I had as an undergrad was actually on neural networks and about these self-organizing maps. Which these co-honen self-organizing maps that basically can do clustering based on some are like kind of like K-means. But on a much more, they can do it better. And you have to get these like nice visualizations out of them. And apparently, there's also some process in our brain. I mean, we have these topographic maps also in our brains. I was always fascinated somehow by these self-organizing maps. And even though I did a lot of like some other things during my PhD, somehow now I'm coming back to this kind of self-organization.\",\n          \"in France so I hope you're having a great time there I will send you the timestamp and of this video when it's on YouTube so Amal says I said I was going to go through these fast but that was a lie and Amal says in this time I'm thinking about studying to take master's degree one of the CS specialties so I would like to consult you and know about helpful recommendations from your background so that may help me to choose one of these fields data science web science artificial intelligence and cyber security whoa that is a lot of fields there look I'm gonna be truth be told it's I can't make a decision for you so my best advice with these things is to dabble is to to go through them with trial and error is to if you want to look at data science try it out if you want to go into web development try it out artificial intelligence cyber security try it out like this what's the you don't need to necessarily learn all of these things at one time as you can just just see how it goes of course and remind yourself building skill in any of those fields will take time right there's no there's no like you see these things as like learn learn programming in three months and all that sort of stuff no that's that's not how it works is that you try these things out you see if it's past your curiosity if it sparks your curiosity you keep going for a little bit more and then you start to build skill and then once you have skill that's when passion starts to come all right a lot of people think is like oh passion I don't have a passion\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"start\",\n      \"properties\": {\n        \"dtype\": \"number\",\n        \"std\": 3156.6774721394336,\n        \"min\": 0.0,\n        \"max\": 37757.66,\n        \"num_unique_values\": 40791,\n        \"samples\": [\n          627.96,\n          1584.1000000000001,\n          4775.9\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"end\",\n      \"properties\": {\n        \"dtype\": \"number\",\n        \"std\": 3157.537277669395,\n        \"min\": 2.18,\n        \"max\": 37772.66,\n        \"num_unique_values\": 41467,\n        \"samples\": [\n          497.12,\n          362.6,\n          503.79999999999995\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    }\n  ]\n}",
       "type": "dataframe",
       "variable_name": "df"
      },
      "text/html": [
       "\n",
       "  <div id=\"df-5eaf8450-cd11-4511-bba1-0f19531cf6bb\" class=\"colab-df-container\">\n",
       "    <div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>title</th>\n",
       "      <th>published</th>\n",
       "      <th>url</th>\n",
       "      <th>video_id</th>\n",
       "      <th>channel_id</th>\n",
       "      <th>id</th>\n",
       "      <th>text</th>\n",
       "      <th>start</th>\n",
       "      <th>end</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>177622</th>\n",
       "      <td>$5 MILLION AI for FREE</td>\n",
       "      <td>2022-08-12 15:18:07</td>\n",
       "      <td>https://youtu.be/3EjtHs_lXnk</td>\n",
       "      <td>3EjtHs_lXnk</td>\n",
       "      <td>UCfzlCWGWYyIQ0aLC5w48gBQ</td>\n",
       "      <td>3EjtHs_lXnk-t0.0</td>\n",
       "      <td>Imagine an AI where all in the same model you ...</td>\n",
       "      <td>0.0</td>\n",
       "      <td>24.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>\n",
       "    <div class=\"colab-df-buttons\">\n",
       "\n",
       "  <div class=\"colab-df-container\">\n",
       "    <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-5eaf8450-cd11-4511-bba1-0f19531cf6bb')\"\n",
       "            title=\"Convert this dataframe to an interactive table.\"\n",
       "            style=\"display:none;\">\n",
       "\n",
       "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\">\n",
       "    <path d=\"M120-120v-720h720v720H120Zm60-500h600v-160H180v160Zm220 220h160v-160H400v160Zm0 220h160v-160H400v160ZM180-400h160v-160H180v160Zm440 0h160v-160H620v160ZM180-180h160v-160H180v160Zm440 0h160v-160H620v160Z\"/>\n",
       "  </svg>\n",
       "    </button>\n",
       "\n",
       "  <style>\n",
       "    .colab-df-container {\n",
       "      display:flex;\n",
       "      gap: 12px;\n",
       "    }\n",
       "\n",
       "    .colab-df-convert {\n",
       "      background-color: #E8F0FE;\n",
       "      border: none;\n",
       "      border-radius: 50%;\n",
       "      cursor: pointer;\n",
       "      display: none;\n",
       "      fill: #1967D2;\n",
       "      height: 32px;\n",
       "      padding: 0 0 0 0;\n",
       "      width: 32px;\n",
       "    }\n",
       "\n",
       "    .colab-df-convert:hover {\n",
       "      background-color: #E2EBFA;\n",
       "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
       "      fill: #174EA6;\n",
       "    }\n",
       "\n",
       "    .colab-df-buttons div {\n",
       "      margin-bottom: 4px;\n",
       "    }\n",
       "\n",
       "    [theme=dark] .colab-df-convert {\n",
       "      background-color: #3B4455;\n",
       "      fill: #D2E3FC;\n",
       "    }\n",
       "\n",
       "    [theme=dark] .colab-df-convert:hover {\n",
       "      background-color: #434B5C;\n",
       "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
       "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
       "      fill: #FFFFFF;\n",
       "    }\n",
       "  </style>\n",
       "\n",
       "    <script>\n",
       "      const buttonEl =\n",
       "        document.querySelector('#df-5eaf8450-cd11-4511-bba1-0f19531cf6bb button.colab-df-convert');\n",
       "      buttonEl.style.display =\n",
       "        google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
       "\n",
       "      async function convertToInteractive(key) {\n",
       "        const element = document.querySelector('#df-5eaf8450-cd11-4511-bba1-0f19531cf6bb');\n",
       "        const dataTable =\n",
       "          await google.colab.kernel.invokeFunction('convertToInteractive',\n",
       "                                                    [key], {});\n",
       "        if (!dataTable) return;\n",
       "\n",
       "        const docLinkHtml = 'Like what you see? Visit the ' +\n",
       "          '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
       "          + ' to learn more about interactive tables.';\n",
       "        element.innerHTML = '';\n",
       "        dataTable['output_type'] = 'display_data';\n",
       "        await google.colab.output.renderOutput(dataTable, element);\n",
       "        const docLink = document.createElement('div');\n",
       "        docLink.innerHTML = docLinkHtml;\n",
       "        element.appendChild(docLink);\n",
       "      }\n",
       "    </script>\n",
       "  </div>\n",
       "\n",
       "\n",
       "    </div>\n",
       "  </div>\n"
      ],
      "text/plain": [
       "                         title            published  \\\n",
       "177622  $5 MILLION AI for FREE  2022-08-12 15:18:07   \n",
       "\n",
       "                                 url     video_id                channel_id  \\\n",
       "177622  https://youtu.be/3EjtHs_lXnk  3EjtHs_lXnk  UCfzlCWGWYyIQ0aLC5w48gBQ   \n",
       "\n",
       "                      id                                               text  \\\n",
       "177622  3EjtHs_lXnk-t0.0  Imagine an AI where all in the same model you ...   \n",
       "\n",
       "        start   end  \n",
       "177622    0.0  24.0  "
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from lancedb.context import contextualize\n",
    "\n",
    "df = (\n",
    "    contextualize(data.to_pandas())\n",
    "    .groupby(\"title\")\n",
    "    .text_col(\"text\")\n",
    "    .window(20)\n",
    "    .stride(4)\n",
    "    .to_pandas()\n",
    ")\n",
    "df.head(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4fe3d190",
   "metadata": {
    "id": "4fe3d190"
   },
   "source": [
    "### Create embedding function\n",
    "To create embeddings out of the text corpus, we'll call the OpenAI embeddings API to get embeddings.\n",
    "Open a free account here and get credits."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "169134a0",
   "metadata": {
    "id": "169134a0"
   },
   "outputs": [],
   "source": [
    "import openai\n",
    "import os\n",
    "\n",
    "# Configuring the environment variable OPENAI_API_KEY\n",
    "if \"OPENAI_API_KEY\" not in os.environ:\n",
    "    # OR set the key here as a variable\n",
    "    openai.api_key = \"sk-proj-....\"\n",
    "\n",
    "assert len(openai.Model.list()[\"data\"]) > 0"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "05377be7",
   "metadata": {
    "id": "05377be7"
   },
   "source": [
    "We'll use the ada2 text embeddings model\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "4aef5764",
   "metadata": {
    "id": "4aef5764"
   },
   "outputs": [],
   "source": [
    "def embed_func(c):\n",
    "    rs = openai.Embedding.create(input=c, engine=\"text-embedding-ada-002\")\n",
    "    return [record[\"embedding\"] for record in rs[\"data\"]]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7da05ea8",
   "metadata": {
    "id": "7da05ea8"
   },
   "source": [
    "### Create the LanceDB Table\n",
    "\n",
    "OpenAI API often fails or times out. So LanceDB's API provides retry and throttling features behind the scenes to make it easier to call these APIs. In LanceDB the primary abstraction you'll use to work with your data is a Table. A Table is designed to store large numbers of columns and huge quantities of data! For those interested, a LanceDB is columnar-based, and uses Lance, an open data format to store data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "f5e76fbf",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 166,
     "referenced_widgets": [
      "b1dfd6f5d5c54844910bf6bff865e456",
      "7e34e229f41046cbb0539b5ab7cbee7e",
      "630f3e09f73945afbc10bc3e7ba0bc97",
      "c1ad06b5624041268bf089cd21b6b032",
      "aad575d484b648cbb46954d4b74b9e60",
      "60fe526ae58749afac6a1420c14e63a8",
      "cd02230b0aad4e18bba25b4788e3adfd",
      "0bcd1304870944b8aa0d08e3597e5d0d",
      "1c671b53eb4643dba8a08b7458276447",
      "ef78d0fcd4a3452e9cf64d38b5d30c01",
      "56a56872d6794ee8910fe2b9b1c158b4"
     ]
    },
    "id": "f5e76fbf",
    "outputId": "e4f93830-8546-40e1-b297-63117a45f08b"
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "<ipython-input-7-f97cb4ac95c6>:4: DeprecationWarning: Function with_embeddings is deprecated and will be removed in a future version\n",
      "  data = with_embeddings(embed_func, df, show_progress=True)\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "b1dfd6f5d5c54844910bf6bff865e456",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "  0%|          | 0/53 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.google.colaboratory.intrinsic+json": {
       "summary": "{\n  \"name\": \"data\",\n  \"rows\": 1,\n  \"fields\": [\n    {\n      \"column\": \"title\",\n      \"properties\": {\n        \"dtype\": \"string\",\n        \"num_unique_values\": 1,\n        \"samples\": [\n          \"$5 MILLION AI for FREE\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"published\",\n      \"properties\": {\n        \"dtype\": \"object\",\n        \"num_unique_values\": 1,\n        \"samples\": [\n          \"2022-08-12 15:18:07\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"url\",\n      \"properties\": {\n        \"dtype\": \"string\",\n        \"num_unique_values\": 1,\n        \"samples\": [\n          \"https://youtu.be/3EjtHs_lXnk\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"video_id\",\n      \"properties\": {\n        \"dtype\": \"string\",\n        \"num_unique_values\": 1,\n        \"samples\": [\n          \"3EjtHs_lXnk\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"channel_id\",\n      \"properties\": {\n        \"dtype\": \"string\",\n        \"num_unique_values\": 1,\n        \"samples\": [\n          \"UCfzlCWGWYyIQ0aLC5w48gBQ\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"id\",\n      \"properties\": {\n        \"dtype\": \"string\",\n        \"num_unique_values\": 1,\n        \"samples\": [\n          \"3EjtHs_lXnk-t0.0\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"text\",\n      \"properties\": {\n        \"dtype\": \"string\",\n        \"num_unique_values\": 1,\n        \"samples\": [\n          \"Imagine an AI where all in the same model you could translate languages, write code, solve crossword puzzles, be a chatbot, and do a whole bunch of other crazy things. This sort of an AI would certainly require a supercomputer of hundreds of A100 GPUs and months of training, even on all that power. We would need a team of researchers, the best of the best. We're talking about a project in the realm of say, 5 plus million dollars. So when you're done, you probably want to keep it to yourself. Maybe you'll sell access via an API, but definitely you can't share the actual model because of AI safety or something like that. What if I told you though, for the last year, a group of over a thousand researchers has been quietly working on their own version of a 176 billion parameter model trained on the nuclear powered supercomputer, the Jonset, and is available now for you to download free of charge. You can download multiple size variants all the way up to 176 billion parameters for free. I'm talking about the BLUM model. BLUM is an acronym that stands for Big Science, Large, Open Science, Open Access, Multilingual. But for all intents and purposes, it's more like big language out of memory. So just how much memory are we talking here? Well, it's going to cost you about 680 gigabyte-ish of memory. You can also run at half precision and use more like 350 gigabytes of memory with likely minimal performance difference in terms of the output quality. But either way, a lot of memory. So I know there are probably like a couple of you guys out there who don't have a Puget workstation with a terabyte of RAM. So what can you do? Well, it turns out that Hugging Face has your back. Not only have they facilitated to a large extent this model's very training and existence, as well as making the model available for you to download for free,\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"start\",\n      \"properties\": {\n        \"dtype\": \"number\",\n        \"std\": null,\n        \"min\": 0.0,\n        \"max\": 0.0,\n        \"num_unique_values\": 1,\n        \"samples\": [\n          0.0\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"end\",\n      \"properties\": {\n        \"dtype\": \"number\",\n        \"std\": null,\n        \"min\": 24.0,\n        \"max\": 24.0,\n        \"num_unique_values\": 1,\n        \"samples\": [\n          24.0\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"vector\",\n      \"properties\": {\n        \"dtype\": \"object\",\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    }\n  ]\n}",
       "type": "dataframe"
      },
      "text/html": [
       "\n",
       "  <div id=\"df-2180441b-88c1-46ce-8463-f68ee408f837\" class=\"colab-df-container\">\n",
       "    <div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>title</th>\n",
       "      <th>published</th>\n",
       "      <th>url</th>\n",
       "      <th>video_id</th>\n",
       "      <th>channel_id</th>\n",
       "      <th>id</th>\n",
       "      <th>text</th>\n",
       "      <th>start</th>\n",
       "      <th>end</th>\n",
       "      <th>vector</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>$5 MILLION AI for FREE</td>\n",
       "      <td>2022-08-12 15:18:07</td>\n",
       "      <td>https://youtu.be/3EjtHs_lXnk</td>\n",
       "      <td>3EjtHs_lXnk</td>\n",
       "      <td>UCfzlCWGWYyIQ0aLC5w48gBQ</td>\n",
       "      <td>3EjtHs_lXnk-t0.0</td>\n",
       "      <td>Imagine an AI where all in the same model you ...</td>\n",
       "      <td>0.0</td>\n",
       "      <td>24.0</td>\n",
       "      <td>[-0.024836179, -0.0009827876, 0.017679991, -0....</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>\n",
       "    <div class=\"colab-df-buttons\">\n",
       "\n",
       "  <div class=\"colab-df-container\">\n",
       "    <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-2180441b-88c1-46ce-8463-f68ee408f837')\"\n",
       "            title=\"Convert this dataframe to an interactive table.\"\n",
       "            style=\"display:none;\">\n",
       "\n",
       "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\">\n",
       "    <path d=\"M120-120v-720h720v720H120Zm60-500h600v-160H180v160Zm220 220h160v-160H400v160Zm0 220h160v-160H400v160ZM180-400h160v-160H180v160Zm440 0h160v-160H620v160ZM180-180h160v-160H180v160Zm440 0h160v-160H620v160Z\"/>\n",
       "  </svg>\n",
       "    </button>\n",
       "\n",
       "  <style>\n",
       "    .colab-df-container {\n",
       "      display:flex;\n",
       "      gap: 12px;\n",
       "    }\n",
       "\n",
       "    .colab-df-convert {\n",
       "      background-color: #E8F0FE;\n",
       "      border: none;\n",
       "      border-radius: 50%;\n",
       "      cursor: pointer;\n",
       "      display: none;\n",
       "      fill: #1967D2;\n",
       "      height: 32px;\n",
       "      padding: 0 0 0 0;\n",
       "      width: 32px;\n",
       "    }\n",
       "\n",
       "    .colab-df-convert:hover {\n",
       "      background-color: #E2EBFA;\n",
       "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
       "      fill: #174EA6;\n",
       "    }\n",
       "\n",
       "    .colab-df-buttons div {\n",
       "      margin-bottom: 4px;\n",
       "    }\n",
       "\n",
       "    [theme=dark] .colab-df-convert {\n",
       "      background-color: #3B4455;\n",
       "      fill: #D2E3FC;\n",
       "    }\n",
       "\n",
       "    [theme=dark] .colab-df-convert:hover {\n",
       "      background-color: #434B5C;\n",
       "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
       "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
       "      fill: #FFFFFF;\n",
       "    }\n",
       "  </style>\n",
       "\n",
       "    <script>\n",
       "      const buttonEl =\n",
       "        document.querySelector('#df-2180441b-88c1-46ce-8463-f68ee408f837 button.colab-df-convert');\n",
       "      buttonEl.style.display =\n",
       "        google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
       "\n",
       "      async function convertToInteractive(key) {\n",
       "        const element = document.querySelector('#df-2180441b-88c1-46ce-8463-f68ee408f837');\n",
       "        const dataTable =\n",
       "          await google.colab.kernel.invokeFunction('convertToInteractive',\n",
       "                                                    [key], {});\n",
       "        if (!dataTable) return;\n",
       "\n",
       "        const docLinkHtml = 'Like what you see? Visit the ' +\n",
       "          '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
       "          + ' to learn more about interactive tables.';\n",
       "        element.innerHTML = '';\n",
       "        dataTable['output_type'] = 'display_data';\n",
       "        await google.colab.output.renderOutput(dataTable, element);\n",
       "        const docLink = document.createElement('div');\n",
       "        docLink.innerHTML = docLinkHtml;\n",
       "        element.appendChild(docLink);\n",
       "      }\n",
       "    </script>\n",
       "  </div>\n",
       "\n",
       "\n",
       "    </div>\n",
       "  </div>\n"
      ],
      "text/plain": [
       "                    title            published                           url  \\\n",
       "0  $5 MILLION AI for FREE  2022-08-12 15:18:07  https://youtu.be/3EjtHs_lXnk   \n",
       "\n",
       "      video_id                channel_id                id  \\\n",
       "0  3EjtHs_lXnk  UCfzlCWGWYyIQ0aLC5w48gBQ  3EjtHs_lXnk-t0.0   \n",
       "\n",
       "                                                text  start   end  \\\n",
       "0  Imagine an AI where all in the same model you ...    0.0  24.0   \n",
       "\n",
       "                                              vector  \n",
       "0  [-0.024836179, -0.0009827876, 0.017679991, -0....  "
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import lancedb\n",
    "from lancedb.embeddings import with_embeddings\n",
    "\n",
    "data = with_embeddings(embed_func, df, show_progress=True)\n",
    "data.to_pandas().head(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5018aeed",
   "metadata": {
    "id": "5018aeed"
   },
   "source": [
    "## Connect to the LanceDB\n",
    "\n",
    "For more information on the lancedb interface, head over to the <a href=\"https://lancedb.github.io/lancedb/python/python/#lancedb.db.DBConnection.create_table\">docs</a>\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "6dee5779",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "6dee5779",
    "outputId": "0bb18586-2411-43d4-f974-e03b5bdab232"
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.10/dist-packages/ipykernel/ipkernel.py:283: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.\n",
      "  and should_run_async(code)\n"
     ]
    }
   ],
   "source": [
    "!rm -rf /tmp/lancedb"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "d9246741",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "d9246741",
    "outputId": "04e23a94-f573-4d26-e3c4-3cd85497b6dd"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "52250"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "db = lancedb.connect(\"/tmp/lancedb\")\n",
    "tbl = db.create_table(\"youtube-chatbot\", data)\n",
    "len(tbl)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f28ff93d",
   "metadata": {
    "id": "f28ff93d"
   },
   "source": [
    "The table is backed by a Lance dataset so it's easy to integrate into other tools (e.g., pandas)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "492762e0",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 98
    },
    "id": "492762e0",
    "outputId": "72b8ca7c-9aa4-4a44-dab5-36bc0d61b10f"
   },
   "outputs": [
    {
     "data": {
      "application/vnd.google.colaboratory.intrinsic+json": {
       "summary": "{\n  \"name\": \"tbl\",\n  \"rows\": 1,\n  \"fields\": [\n    {\n      \"column\": \"title\",\n      \"properties\": {\n        \"dtype\": \"string\",\n        \"num_unique_values\": 1,\n        \"samples\": [\n          \"$5 MILLION AI for FREE\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"published\",\n      \"properties\": {\n        \"dtype\": \"object\",\n        \"num_unique_values\": 1,\n        \"samples\": [\n          \"2022-08-12 15:18:07\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"url\",\n      \"properties\": {\n        \"dtype\": \"string\",\n        \"num_unique_values\": 1,\n        \"samples\": [\n          \"https://youtu.be/3EjtHs_lXnk\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"video_id\",\n      \"properties\": {\n        \"dtype\": \"string\",\n        \"num_unique_values\": 1,\n        \"samples\": [\n          \"3EjtHs_lXnk\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"channel_id\",\n      \"properties\": {\n        \"dtype\": \"string\",\n        \"num_unique_values\": 1,\n        \"samples\": [\n          \"UCfzlCWGWYyIQ0aLC5w48gBQ\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"id\",\n      \"properties\": {\n        \"dtype\": \"string\",\n        \"num_unique_values\": 1,\n        \"samples\": [\n          \"3EjtHs_lXnk-t0.0\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"text\",\n      \"properties\": {\n        \"dtype\": \"string\",\n        \"num_unique_values\": 1,\n        \"samples\": [\n          \"Imagine an AI where all in the same model you could translate languages, write code, solve crossword puzzles, be a chatbot, and do a whole bunch of other crazy things. This sort of an AI would certainly require a supercomputer of hundreds of A100 GPUs and months of training, even on all that power. We would need a team of researchers, the best of the best. We're talking about a project in the realm of say, 5 plus million dollars. So when you're done, you probably want to keep it to yourself. Maybe you'll sell access via an API, but definitely you can't share the actual model because of AI safety or something like that. What if I told you though, for the last year, a group of over a thousand researchers has been quietly working on their own version of a 176 billion parameter model trained on the nuclear powered supercomputer, the Jonset, and is available now for you to download free of charge. You can download multiple size variants all the way up to 176 billion parameters for free. I'm talking about the BLUM model. BLUM is an acronym that stands for Big Science, Large, Open Science, Open Access, Multilingual. But for all intents and purposes, it's more like big language out of memory. So just how much memory are we talking here? Well, it's going to cost you about 680 gigabyte-ish of memory. You can also run at half precision and use more like 350 gigabytes of memory with likely minimal performance difference in terms of the output quality. But either way, a lot of memory. So I know there are probably like a couple of you guys out there who don't have a Puget workstation with a terabyte of RAM. So what can you do? Well, it turns out that Hugging Face has your back. Not only have they facilitated to a large extent this model's very training and existence, as well as making the model available for you to download for free,\"\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"start\",\n      \"properties\": {\n        \"dtype\": \"number\",\n        \"std\": null,\n        \"min\": 0.0,\n        \"max\": 0.0,\n        \"num_unique_values\": 1,\n        \"samples\": [\n          0.0\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"end\",\n      \"properties\": {\n        \"dtype\": \"number\",\n        \"std\": null,\n        \"min\": 24.0,\n        \"max\": 24.0,\n        \"num_unique_values\": 1,\n        \"samples\": [\n          24.0\n        ],\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    },\n    {\n      \"column\": \"vector\",\n      \"properties\": {\n        \"dtype\": \"object\",\n        \"semantic_type\": \"\",\n        \"description\": \"\"\n      }\n    }\n  ]\n}",
       "type": "dataframe"
      },
      "text/html": [
       "\n",
       "  <div id=\"df-b865f122-44b1-4c88-bcaf-fe103aabdcae\" class=\"colab-df-container\">\n",
       "    <div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>title</th>\n",
       "      <th>published</th>\n",
       "      <th>url</th>\n",
       "      <th>video_id</th>\n",
       "      <th>channel_id</th>\n",
       "      <th>id</th>\n",
       "      <th>text</th>\n",
       "      <th>start</th>\n",
       "      <th>end</th>\n",
       "      <th>vector</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>$5 MILLION AI for FREE</td>\n",
       "      <td>2022-08-12 15:18:07</td>\n",
       "      <td>https://youtu.be/3EjtHs_lXnk</td>\n",
       "      <td>3EjtHs_lXnk</td>\n",
       "      <td>UCfzlCWGWYyIQ0aLC5w48gBQ</td>\n",
       "      <td>3EjtHs_lXnk-t0.0</td>\n",
       "      <td>Imagine an AI where all in the same model you ...</td>\n",
       "      <td>0.0</td>\n",
       "      <td>24.0</td>\n",
       "      <td>[-0.024836179, -0.0009827876, 0.017679991, -0....</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>\n",
       "    <div class=\"colab-df-buttons\">\n",
       "\n",
       "  <div class=\"colab-df-container\">\n",
       "    <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-b865f122-44b1-4c88-bcaf-fe103aabdcae')\"\n",
       "            title=\"Convert this dataframe to an interactive table.\"\n",
       "            style=\"display:none;\">\n",
       "\n",
       "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\">\n",
       "    <path d=\"M120-120v-720h720v720H120Zm60-500h600v-160H180v160Zm220 220h160v-160H400v160Zm0 220h160v-160H400v160ZM180-400h160v-160H180v160Zm440 0h160v-160H620v160ZM180-180h160v-160H180v160Zm440 0h160v-160H620v160Z\"/>\n",
       "  </svg>\n",
       "    </button>\n",
       "\n",
       "  <style>\n",
       "    .colab-df-container {\n",
       "      display:flex;\n",
       "      gap: 12px;\n",
       "    }\n",
       "\n",
       "    .colab-df-convert {\n",
       "      background-color: #E8F0FE;\n",
       "      border: none;\n",
       "      border-radius: 50%;\n",
       "      cursor: pointer;\n",
       "      display: none;\n",
       "      fill: #1967D2;\n",
       "      height: 32px;\n",
       "      padding: 0 0 0 0;\n",
       "      width: 32px;\n",
       "    }\n",
       "\n",
       "    .colab-df-convert:hover {\n",
       "      background-color: #E2EBFA;\n",
       "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
       "      fill: #174EA6;\n",
       "    }\n",
       "\n",
       "    .colab-df-buttons div {\n",
       "      margin-bottom: 4px;\n",
       "    }\n",
       "\n",
       "    [theme=dark] .colab-df-convert {\n",
       "      background-color: #3B4455;\n",
       "      fill: #D2E3FC;\n",
       "    }\n",
       "\n",
       "    [theme=dark] .colab-df-convert:hover {\n",
       "      background-color: #434B5C;\n",
       "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
       "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
       "      fill: #FFFFFF;\n",
       "    }\n",
       "  </style>\n",
       "\n",
       "    <script>\n",
       "      const buttonEl =\n",
       "        document.querySelector('#df-b865f122-44b1-4c88-bcaf-fe103aabdcae button.colab-df-convert');\n",
       "      buttonEl.style.display =\n",
       "        google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
       "\n",
       "      async function convertToInteractive(key) {\n",
       "        const element = document.querySelector('#df-b865f122-44b1-4c88-bcaf-fe103aabdcae');\n",
       "        const dataTable =\n",
       "          await google.colab.kernel.invokeFunction('convertToInteractive',\n",
       "                                                    [key], {});\n",
       "        if (!dataTable) return;\n",
       "\n",
       "        const docLinkHtml = 'Like what you see? Visit the ' +\n",
       "          '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
       "          + ' to learn more about interactive tables.';\n",
       "        element.innerHTML = '';\n",
       "        dataTable['output_type'] = 'display_data';\n",
       "        await google.colab.output.renderOutput(dataTable, element);\n",
       "        const docLink = document.createElement('div');\n",
       "        docLink.innerHTML = docLinkHtml;\n",
       "        element.appendChild(docLink);\n",
       "      }\n",
       "    </script>\n",
       "  </div>\n",
       "\n",
       "\n",
       "    </div>\n",
       "  </div>\n"
      ],
      "text/plain": [
       "                    title            published                           url  \\\n",
       "0  $5 MILLION AI for FREE  2022-08-12 15:18:07  https://youtu.be/3EjtHs_lXnk   \n",
       "\n",
       "      video_id                channel_id                id  \\\n",
       "0  3EjtHs_lXnk  UCfzlCWGWYyIQ0aLC5w48gBQ  3EjtHs_lXnk-t0.0   \n",
       "\n",
       "                                                text  start   end  \\\n",
       "0  Imagine an AI where all in the same model you ...    0.0  24.0   \n",
       "\n",
       "                                              vector  \n",
       "0  [-0.024836179, -0.0009827876, 0.017679991, -0....  "
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tbl.to_pandas().head(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dc3c6895",
   "metadata": {
    "id": "dc3c6895"
   },
   "source": [
    "### Create and answer the prompt\n",
    "For a given context (bunch of text), we can ask the OpenAI Completion API to answer an arbitrary question using the following prompt:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "0d9b0f5f",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "0d9b0f5f",
    "outputId": "c166d73a-3364-4476-df84-df3eba0716d6"
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.10/dist-packages/ipykernel/ipkernel.py:283: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.\n",
      "  and should_run_async(code)\n"
     ]
    }
   ],
   "source": [
    "def create_prompt(query, context):\n",
    "    limit = 3750\n",
    "\n",
    "    prompt_start = \"Answer the question based on the context below.\\n\\n\" + \"Context:\\n\"\n",
    "    prompt_end = f\"\\n\\nQuestion: {query}\\nAnswer:\"\n",
    "    # append contexts until hitting limit\n",
    "    for i in range(1, len(context)):\n",
    "        if len(\"\\n\\n---\\n\\n\".join(context.text[:i])) >= limit:\n",
    "            prompt = (\n",
    "                prompt_start + \"\\n\\n---\\n\\n\".join(context.text[: i - 1]) + prompt_end\n",
    "            )\n",
    "            break\n",
    "        elif i == len(context) - 1:\n",
    "            prompt = prompt_start + \"\\n\\n---\\n\\n\".join(context.text) + prompt_end\n",
    "    return prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "a3360c7f",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 36
    },
    "id": "a3360c7f",
    "outputId": "2e45dc2f-5077-4ce6-eb2b-59c976dd93a5"
   },
   "outputs": [
    {
     "data": {
      "application/vnd.google.colaboratory.intrinsic+json": {
       "type": "string"
      },
      "text/plain": [
       "'The 12th person on the moon was Eugene Cernan, who landed on December 11, 1972 as part of the Apollo 17 mission.'"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def complete(prompt):\n",
    "    # query text-davinci-003\n",
    "    res = openai.Completion.create(\n",
    "        engine=\"gpt-3.5-turbo-instruct\",\n",
    "        prompt=prompt,\n",
    "        temperature=0,\n",
    "        max_tokens=400,\n",
    "        top_p=1,\n",
    "        frequency_penalty=0,\n",
    "        presence_penalty=0,\n",
    "        stop=None,\n",
    "    )\n",
    "    return res[\"choices\"][0][\"text\"].strip()\n",
    "\n",
    "\n",
    "# check that it works\n",
    "query = \"who was the 12th person on the moon and when did they land?\"\n",
    "complete(query)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e4b12ee5",
   "metadata": {
    "id": "e4b12ee5"
   },
   "source": [
    "Let's put it all together now"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "6fac2cf0",
   "metadata": {
    "id": "6fac2cf0"
   },
   "outputs": [],
   "source": [
    "query = (\n",
    "    \"Which training method should I use for sentence transformers \"\n",
    "    \"when I only have pairs of related sentences?\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "26a68c79",
   "metadata": {
    "id": "26a68c79"
   },
   "outputs": [],
   "source": [
    "# Embed the question\n",
    "emb = embed_func(query)[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f628fb47",
   "metadata": {
    "id": "f628fb47"
   },
   "source": [
    "Again we'll use `LanceDB's chaining query API`. This time, we'll perform similarity search to find similar embeddings to our query. We can easily tweak the parameters in the query to produce the best result.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "7c77d945",
   "metadata": {
    "id": "7c77d945"
   },
   "outputs": [],
   "source": [
    "# Use LanceDB to get top 3 most relevant context\n",
    "context = tbl.search(emb).limit(3).to_pandas()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "605c35a0",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 36
    },
    "id": "605c35a0",
    "outputId": "ac8ba968-aa66-4f27-8b7d-78a1ddb0586f"
   },
   "outputs": [
    {
     "data": {
      "application/vnd.google.colaboratory.intrinsic+json": {
       "type": "string"
      },
      "text/plain": [
       "'You can use NLI with multiple negative ranking loss or STS with cosine similarity loss.'"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Get the answer from completion API\n",
    "prompt = create_prompt(query, context)\n",
    "complete(prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "ac9aeedf",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 321
    },
    "id": "ac9aeedf",
    "outputId": "8447ee0b-e373-46e0-ba73-5218e61bc91b"
   },
   "outputs": [
    {
     "data": {
      "image/jpeg": "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\n",
      "text/html": [
       "\n",
       "        <iframe\n",
       "            width=\"400\"\n",
       "            height=\"300\"\n",
       "            src=\"https://www.youtube.com/embed/pNvujJ1XyeQ?start=289\"\n",
       "            frameborder=\"0\"\n",
       "            allowfullscreen\n",
       "            \n",
       "        ></iframe>\n",
       "        "
      ],
      "text/plain": [
       "<IPython.lib.display.YouTubeVideo at 0x7caee3180d90>"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import YouTubeVideo\n",
    "\n",
    "top_match = context.iloc[0]\n",
    "YouTubeVideo(top_match[\"url\"].split(\"/\")[-1], start=int(top_match[\"start\"]))"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
